package com.baymax.test.scene.replace

import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject

object StringTemplateUtilV2 {
    private const val TAG = "StringTemplateUtil"
    private val DEF_REGEX_2 = "\\$\\{(.+?)\\}".toRegex()
    private val DEF_REGEX_3 = "\"?\\\$\\{(\\w*\\(?(\\w*)\\)?)\\}\"?".toRegex()


    @JvmOverloads
    fun replace(
        template: String, data: MutableMap<String, String>, regex: Regex = DEF_REGEX_3
    ): JSONObject {
        return kotlin.runCatching {
            var templateOrNew = template
            log(TAG, "replace template:%s start1 $templateOrNew")
            val matchResults = regex.findAll(template).toList()
            //${uid} to data[uid]
            val notStartQuote = mutableSetOf<String>()
            val matcherKeysValues = matchResults.associate { mr ->
                val k = mr.groupValues.last(String::isNotBlank)
                if (!mr.value.startsWith("\"")){
                    notStartQuote.add(mr.value)
                }
                mr.value.replace("\"" ,"") to data[k].orEmpty()
            }
            log(TAG, "replace $notStartQuote matcherKeysValues $matcherKeysValues"  )

            notStartQuote.onEach {
                templateOrNew = template.replace(it, "\"${it}\"")
                log(TAG, "replace template:%s start2 $templateOrNew ")
            }
            val templateJson = JSONObject.parse(templateOrNew) as JSONObject
//           doReplaceObject(templateJson, matcherKeysValues)
            templateJson.walkTree { k, v ->
                if (matcherKeysValues.containsKey(v)){
                    this[k] = matcherKeysValues[v]
                }
            }
            templateJson
        }.onFailure {
            log(TAG, "replace fail $it")
        }.getOrDefault(JSONObject())
    }

    private fun doReplaceObject(templateJson: JSONObject, map: Map<String, String>) {
        templateJson.onEach { (k, v) ->
            when (v) {
                is JSONObject -> {
                    doReplaceObject(v, map)
                }
                is JSONArray -> {
                    doReplaceArray(v, map)
                }
                else -> {
                    //替换value
                    if (map.containsKey(v)){
                        templateJson[k] = map[v]
                    }
                }
            }

        }
    }

    private fun doReplaceArray(templateJson: JSONArray, map: Map<String, String>) {
        templateJson.onEach { arr ->
            if (arr is JSONArray) {
                doReplaceArray(arr, map)
            }
            if (arr is JSONObject) {
                doReplaceObject(arr, map)
            }
        }

    }

    fun log(tag: String, msg: String) {
        println("$tag : $msg")
    }

    private fun JSONObject.walkTree(entryAction: JSONObject.(String, Any) -> Unit) {
        this.onEach { (k, v) ->
            when (v) {
                is JSONObject -> {
                    v.walkTree(entryAction)
                }
                is JSONArray -> {
                    v.walkTree(entryAction)
                }
                else -> entryAction(k, v)
            }
        }

    }

    private fun JSONArray.walkTree(entryAction: JSONObject.(String, Any) -> Unit) {
        this.onEach { v ->
            if (v is JSONArray) {
                v.walkTree(entryAction)
            }
            if (v is JSONObject) {
                v.walkTree(entryAction)
            }
        }

    }

}